package com.xiaochong.tir.api.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.tir.api.component.HbaseBaseQueryComponent;
import com.xiaochong.tir.api.component.RedisCacheComponent;
import com.xiaochong.service.common.config.redis.RedisServer;
import com.xiaochong.tir.api.util.ListSortUtil;
import com.xiaochong.tir.common.data.hbasepo.TradesHistoryCountFive;
import com.xiaochong.tir.common.data.hbasepo.TradesToKLine;
import com.xiaochong.tir.common.data.mapper.*;
import com.xiaochong.tir.common.data.po.*;
import com.xiaochong.tir.common.data.vo.*;
import com.xiaochong.tir.common.util.ApiResultCodeUtils;
import com.xiaochong.tir.common.util.DateUtils;
import com.xiaochong.tir.common.util.HbaseTableUtils;
import com.xiaochong.tir.common.util.RedisKeysUtils;
import net.sf.json.util.JSONTokener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 此类为[基础代码]自动生成,已经拥有基本的增删改成操作 
 * <其他请自行扩展>
 * @author mengxiangdong
 * @time 2018-05-23 14:07
 *
 */
@Service("webSocketService")
public class WebSocketService {


    @Autowired
    private ExchangeInfoMapper exchangeInfoDao;

    @Autowired
    private ListedCompanyIndexMapper listedCompanyIndexMapper;

    @Autowired
    private NonListedCompanyIndexMapper nonListedCompanyIndexMapper;

    @Autowired
    private ConceptCategoryMapper conceptCategoryMapper;

    @Autowired
    private RedisServer redisServer;

    @Autowired
    private RedisCacheComponent redisCacheComponent;

    @Autowired
    private CurrencyInfoMapper currencyInfoMapper;

    @Autowired
    private ConceptCategoryMapper conceptCategoryMapperp;

    @Autowired
    private HbaseBaseQueryComponent hbaseBaseQueryComponent;

    @Autowired
    private CurrencyIndustryCategoryMapper currencyIndustryCategoryMapper;

    @Autowired
    private SyResearchReportMapper syResearchReportMapper;

    @Autowired
    private SyResearchReportFileMapper syResearchReportFileMapper;

    @Autowired
    private SyRotationMapMapper syRotationMapMapper;

    @Autowired
    private SyChannelsMapper syChannelsMapper;

    @Autowired
    private ExchangeInfoService exchangeInfoService;

    @Autowired
    private ExchangeTransactionpairMiddleMapper exchangeTransactionpairMiddleMapper;

    @Autowired
    private TransactionPairMapper transactionPairMapper;

    @Autowired
    private ExchangeDimensionMiddleMapper exchangeDimensionMiddleMapper;

    /**
     * 买卖单
     */
    public String orderBook(int exchangeId, int transactionId) {
        try {
            ExchangeTransactionpairMiddle query = new ExchangeTransactionpairMiddle();;
            query.setTransactionId(transactionId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = exchangeTransactionpairMiddleMapper.selectByEntity(query);
            if(exchangeTransactionpairMiddle == null || !exchangeTransactionpairMiddle.getEnableFlag()){
                LogTrace.info("orderBook","exchangeTransactionpairMiddle",transactionId+"查询不可用");
                return null;
            }
                    String Rediskey = RedisKeysUtils.API_SERVICE_ORDER_BOOK+"@"+exchangeId+"@"+exchangeTransactionpairMiddle.getTransactionName();

                    String API_SERVICE_ORDER_BOOK=redisServer.get(Rediskey);
                        //hbase
                        if (API_SERVICE_ORDER_BOOK==null){
                            String rowKey = HbaseTableUtils.API_SERVICE_ORDER_BOOK_ROWKEY+"@"+exchangeId+"@"+exchangeTransactionpairMiddle.getTransactionName();

                            API_SERVICE_ORDER_BOOK = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.API_SERVICE_ORDER_BOOK_TABLE_NAME
                                    , HbaseTableUtils.API_SERVICE_ORDER_BOOK_TABLE_NAME_FAMILY
                                    , HbaseTableUtils.API_SERVICE_ORDER_BOOK_QUALIFIER
                                    , rowKey
                            );
                        }
                        if (API_SERVICE_ORDER_BOOK!=null){
                            ApiWebSocketVo vo=new ApiWebSocketVo();
                            vo.setData(API_SERVICE_ORDER_BOOK);
                            vo.setExplain("买卖单");
                            vo.setType("1");
                            return JSON.toJSONString(vo);
                        }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("买卖单",e);
        }
        return null;
    }

    /**
     * k线数据-K线图
     */
    public String kAction(int exchangeId, int transactionId) {
        try {
            ExchangeTransactionpairMiddle query = new ExchangeTransactionpairMiddle();;
            query.setTransactionId(transactionId);
            query.setExchangeId( exchangeId );
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = exchangeTransactionpairMiddleMapper.selectByEntity(query);
            if(exchangeTransactionpairMiddle == null || !exchangeTransactionpairMiddle.getEnableFlag()){
                LogTrace.info("kAction","exchangeTransactionpairMiddle",transactionId+"查询不可用");
                return null;
            }
                        //redis
                        String Rediskey = RedisKeysUtils.API_SERVICE_K_ACTION+"@"+exchangeId+"@"+exchangeTransactionpairMiddle.getTransactionName();
                        String API_SERVICE_K_ACTION=redisServer.get(Rediskey);
                        //hbase
                        if (API_SERVICE_K_ACTION==null){
                            int d=0;
                            while (true){
                                Long nowTIme=DateUtils.getCurrentDataLong();
                                LocalDateTime time = DateUtils.getDateTimeOfTimestamp(nowTIme-d);
                                String rowKey = exchangeId+"@"+exchangeTransactionpairMiddle.getTransactionName()+"@"+DateUtils.localDateTimeFormatString(time,DateUtils.format_ymdhm);
                                API_SERVICE_K_ACTION = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME
                                        , HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME_FAMILY
                                        , HbaseTableUtils.API_SERVICE_K_ACTION_QUALIFIER
                                        , rowKey
                                );
                                //只取一天内最新数据
                                if (API_SERVICE_K_ACTION!=null||d>86400000){
                                    break;
                                }
                                d=d+60000;
                            }
                        }
                        if (API_SERVICE_K_ACTION!=null){
                            ApiWebSocketVo vo=new ApiWebSocketVo();
                            vo.setData(API_SERVICE_K_ACTION);
                            vo.setExplain("k线数据-K线图");
                            vo.setType("2");

                            //判断数据是否已经推过
                            return JSON.toJSONString(vo);
                        }

        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("k线数据-K线图",e);
        }
        return null;
    }

    /**
     * k线数据-历史交易
     */
    public String tranes(int exchangeId, int transactionId) {
        try {

            ExchangeTransactionpairMiddle query = new ExchangeTransactionpairMiddle();;
            query.setTransactionId(transactionId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = exchangeTransactionpairMiddleMapper.selectByEntity(query);
            if(exchangeTransactionpairMiddle == null || !exchangeTransactionpairMiddle.getEnableFlag()){
                LogTrace.info("tranes","exchangeTransactionpairMiddle",transactionId+"查询不可用");
                return null;
            }
            //redis
            String Rediskey = RedisKeysUtils.API_SERVICE_TRADES + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
            String API_SERVICE_TRADES = redisServer.get( Rediskey );
            //hbase
            if (API_SERVICE_TRADES == null) {
                int d = 0;
                while (true) {
                    Long nowTIme = DateUtils.getCurrentDataLong();
                    LocalDateTime time = DateUtils.getDateTimeOfTimestamp( nowTIme - d );
                    String rowKey = DateUtils.localDateTimeFormatString( time, DateUtils.format_ymdhm ) + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
                    ;
                    API_SERVICE_TRADES = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME
                            , HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME_FAMILY
                            , HbaseTableUtils.API_SERVICE_TRADES_QUALIFIER
                            , rowKey
                    );
                    //只取一天内最新数据
                    if (API_SERVICE_TRADES != null || d > 86400000) {
                        break;
                    }
                    d = d + 60000;
                }
            }
            if (API_SERVICE_TRADES != null) {
                ApiWebSocketVo vo = new ApiWebSocketVo();
                vo.setData( API_SERVICE_TRADES );
                vo.setExplain( "k线数据-历史交易" );
                vo.setType( "3" );
                return JSON.toJSONString( vo );
            }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("k线数据-历史交易",e);
        }
        return  null;
    }


    /**
     * k线数据-深度
     */
    public String depth(int exchangeId, int transactionId) {
        try {

            ExchangeTransactionpairMiddle query = new ExchangeTransactionpairMiddle();;
            query.setTransactionId(transactionId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = exchangeTransactionpairMiddleMapper.selectByEntity(query);
            if(exchangeTransactionpairMiddle == null || !exchangeTransactionpairMiddle.getEnableFlag()){
                LogTrace.info("depth","exchangeTransactionpairMiddle",transactionId+"查询不可用");
                return null;
            }
                //redis
                String Rediskey = RedisKeysUtils.API_SERVICE_DEPTH + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
                String API_SERVICE_ORDER_BOOK = redisServer.get( Rediskey );
                //hbase
                if (API_SERVICE_ORDER_BOOK == null) {
                    String rowKey = HbaseTableUtils.API_SERVICE_DEPTH_ROWKEY + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
                    API_SERVICE_ORDER_BOOK = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.API_SERVICE_DEPTH_TABLE_NAME
                            , HbaseTableUtils.API_SERVICE_DEPTH_TABLE_NAME_FAMILY
                            , HbaseTableUtils.API_SERVICE_DEPTH_QUALIFIER
                            , rowKey
                    );
                }

                //最新成交价
                Long nowTImeres = DateUtils.getCurrentDataLong();
                LocalDateTime timeres = DateUtils.getDateTimeOfTimestamp( nowTImeres );
                String redisPriceDate = DateUtils.localDateTimeFormatString(timeres,DateUtils.format_ymds);
                String Rediskey2 = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
                String API_SERVICE_K_ACTION_CHANGE_PRICE = redisServer.get( Rediskey2 );
                if(API_SERVICE_K_ACTION_CHANGE_PRICE!=null){
                    JSONObject object = JSON.parseObject( API_SERVICE_K_ACTION_CHANGE_PRICE );
                    if (object.containsKey( "lastOpenPrice" )){
                        Double lastOpenPrice = Double.parseDouble(object.get( "lastOpenPrice" ).toString());
                        if (lastOpenPrice!=null){
                            DePthResultVo resultVo=new DePthResultVo();
                            List<DepthVo> asksList=new ArrayList<>(  );
                            List<DepthVo> bidsList=new ArrayList<>(  );

                            if (API_SERVICE_ORDER_BOOK != null) {
                                JSONObject jsonObject = JSON.parseObject( API_SERVICE_ORDER_BOOK );
                                JSONArray asks= (JSONArray) jsonObject.get( "asks" );
                                JSONArray bids= (JSONArray) jsonObject.get( "bids" );

                                ListSortUtil sortUtil=new ListSortUtil();
                                JSONArray asksOb = JSON.parseArray( asks.get( asks.size()-1 ).toString() );
                                BigDecimal asksPr = asksOb.getBigDecimal( 0 );
                                BigDecimal maxPrice=asksPr;

                                JSONArray bidsObj = JSON.parseArray( bids.get( bids.size()-1 ).toString() );
                                BigDecimal bidsPr = bidsObj.getBigDecimal( 0 );
                                BigDecimal minPrice=bidsPr;

                                //刻度计算
                                double interval= (lastOpenPrice-minPrice.doubleValue())/20;
                                double interval2= (maxPrice.doubleValue()-lastOpenPrice)/20;

                                for(int j=0;j<20;j++){
                                    Double asksCount=0.00;
                                    DepthVo asksvo=new DepthVo();
                                for(int i=0;i<bids.size();i++){
                                    JSONArray asksObject = JSON.parseArray( bids.get( i ).toString() );
                                    BigDecimal asksPrice = asksObject.getBigDecimal( 0 );
                                        if(asksPrice.doubleValue()<=(lastOpenPrice-interval*j) && asksPrice.doubleValue()>=lastOpenPrice-(interval*(j+1))){
                                            asksCount=asksCount+Double.parseDouble(asksObject.get( 1)+"");
                                        }
                                    }
                                    if(j>=1){
                                        asksvo.setCount(asksCount+asksList.get( j-1 ).getCount());
                                    }else{
                                        asksvo.setCount(asksCount);
                                    }
                                    asksvo.setPrice(lastOpenPrice-interval*j);
                                    if (asksvo.getCount()==null)asksvo.setCount( 0.00 );
                                    asksList.add( asksvo );

                                    Double bidsCount=0.00;
                                    DepthVo bidsvo=new DepthVo();
                                    for(int i =0;i<asks.size();i++){
                                        JSONArray bidsObject = JSON.parseArray( asks.get( i ).toString() );
                                        BigDecimal bidsPrice = bidsObject.getBigDecimal( 0 );

                                        if(bidsPrice.doubleValue()>=lastOpenPrice+interval2*j && bidsPrice.doubleValue()<=lastOpenPrice+(interval2*(j+1))){
                                            bidsCount=bidsCount+Double.parseDouble(bidsObject.get( 1)+"");
                                        }
                                    }
                                    if(j>=1){
                                        bidsvo.setCount(bidsCount+bidsList.get( j-1 ).getCount());
                                    }else{
                                        bidsvo.setCount(bidsCount);
                                    }
                                    bidsvo.setPrice(lastOpenPrice+interval2*(j+1));
                                    if (bidsvo.getCount()==null)bidsvo.setCount( 0.00 );
                                    bidsList.add( bidsvo );
                                }

                                sortUtil.mySort( bidsList,"price","asc" );
                                sortUtil.mySort( asksList,"price","asc" );
                                resultVo.setAsksList( bidsList );
                                resultVo.setBidsList( asksList );

                                ApiWebSocketVo apiWebSocketVo = new ApiWebSocketVo();
                                apiWebSocketVo.setData( resultVo );
                                apiWebSocketVo.setExplain( "k线数据-深度"+lastOpenPrice);
                                apiWebSocketVo.setType( "4" );
                                return JSON.toJSONString( apiWebSocketVo );
                            }
                        }
                    }
                }


        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("k线数据-深度",e);
        }
        return null;
    }

    /**
     * k线表头数据
     */
    public String rise(int exchangeId, int transactionId) {
        try {
            ExchangeTransactionpairMiddle query = new ExchangeTransactionpairMiddle();;
            query.setTransactionId(transactionId);
            ExchangeTransactionpairMiddle exchangeTransactionpairMiddle = exchangeTransactionpairMiddleMapper.selectByEntity(query);
            if(exchangeTransactionpairMiddle == null || !exchangeTransactionpairMiddle.getEnableFlag()){
                LogTrace.info("rise","exchangeTransactionpairMiddle",transactionId+"查询不可用");
                return null;
            }
            //redis
            Long nowTImeres = DateUtils.getCurrentDataLong();
            LocalDateTime timeres = DateUtils.getDateTimeOfTimestamp( nowTImeres );
            String redisPriceDate = DateUtils.localDateTimeFormatString(timeres,DateUtils.format_ymds);
            String Rediskey = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE + "@" + exchangeId + "@" + exchangeTransactionpairMiddle.getTransactionName();
            String API_SERVICE_K_ACTION_CHANGE_PRICE = redisServer.get( Rediskey );

            List<String> list=new ArrayList<>(  );
            int d=0;
            while (true) {
               /* Long nowTIme = DateUtils.getCurrentDataLong();
                LocalDateTime time = DateUtils.getDateTimeOfTimestamp( nowTIme-d );
                int minu = time.getMinute()/5;
                String timePart = DateUtils.localDateTimeFormatString(time,DateUtils.format_ymdh);

                timePart += minu < 10 ? "0"+minu:minu;*/
                LocalDateTime timeres2 = DateUtils.getDateTimeOfTimestamp( nowTImeres-d );
                String lastRowKey = DateUtils.localDateTimeFormatString(timeres2,DateUtils.format_ymdhm);//当前时间转成分钟
                String rowKey = HbaseTableUtils.API_SERVICE_TRADES_PART__ROWKEY+"@"+exchangeId+"@"+exchangeTransactionpairMiddle.getTransactionName()+"@"+lastRowKey;

                String API_SERVICE_TRADES = hbaseBaseQueryComponent.selectByQualifierData( HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME
                        , HbaseTableUtils.API_SERVICE_TRADES_TABLE_NAME_FAMILY
                        , HbaseTableUtils.API_SERVICE_TRADES_QUALIFIER
                        , rowKey
                );
                if(API_SERVICE_TRADES != null){
                    list.add( API_SERVICE_TRADES );
                }
                if ( d > 86400000) {
                    break;
                }
                d = d + 60000;
            }

            BigDecimal allAmount=new BigDecimal( 0 );
            for(int i=0;i<list.size();i++){
                String object=list.get( i );
                if (object!=null){
                    TradesHistoryCountFive five=JSON.parseObject( object, TradesHistoryCountFive.class );
                    allAmount=allAmount.add(  five.getAmount());
                }
            }
            if (API_SERVICE_K_ACTION_CHANGE_PRICE != null) {
                ApiWebSocketVo vo = new ApiWebSocketVo();

                JSONObject jsonObject = JSON.parseObject( API_SERVICE_K_ACTION_CHANGE_PRICE );
                jsonObject.put( "allAmount", allAmount);
                vo.setData( jsonObject );
                vo.setExplain( "k线表头数据");
                vo.setType( "5" );
                return JSON.toJSONString( vo );
            }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("k线表头数据",e);
        }
        return null;
    }

    /**
     * 根据日期获取当天数据
     * @param kDate
     * @param exchangeId
     * @param transactionName
     * @return
     */
    public List<String> getKActionOfDate(String kDate, Integer exchangeId, String transactionName,List<String> dataOfdate) throws Exception{
        LogTrace.infoKvs("根据日期获取当天数据Theard-Start","kDate",kDate,"exchangeId",String.valueOf(exchangeId),"transactionName",transactionName);
        //List<String> resultList = new ArrayList<>();
        String grailStr=null;
        TradesToKLine tradesToKLine;
        Long nowTImeres = DateUtils.getLongTIme( kDate );
        LocalDateTime timeres = DateUtils.getDateTimeOfTimestamp( nowTImeres);
        for(int i=0;i<1440;i++){
            //timeres = timeres.minusMinutes(1);
            String lastRowKey = DateUtils.localDateTimeFormatString(timeres,DateUtils.format_ymdhm);//当前时间转成分钟
            String rowKey = exchangeId+"@"+transactionName+"@"+lastRowKey;
           // System.out.println(rowKey);
            grailStr = hbaseBaseQueryComponent.selectByQualifierData(HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME
                    , HbaseTableUtils.API_SERVICE_K_ACTION_TABLE_NAME_FAMILY
                    , HbaseTableUtils.API_SERVICE_K_ACTION_QUALIFIER
                    , rowKey
            );
            if (grailStr!=null){
                Object listArray = new JSONTokener(grailStr).nextValue();
                if(listArray instanceof  net.sf.json.JSONArray){//老数据兼容问题
                    JSONArray jsonArray = JSON.parseArray(grailStr);
                    tradesToKLine = new TradesToKLine();
                    tradesToKLine.setTimestamp(jsonArray.getString(0));
                    tradesToKLine.setOpenPrice(jsonArray.getString(1));
                    tradesToKLine.setHighestPrice(jsonArray.getString(2));
                    tradesToKLine.setLowestPrice(jsonArray.getString(3));
                    tradesToKLine.setClosePrice(jsonArray.getString(4));
                    tradesToKLine.setVolume(jsonArray.getString(5));
                    dataOfdate.add(JSON.toJSONString(tradesToKLine));
                }else{
                    dataOfdate.add( grailStr );
                }
            }
            timeres = timeres.plusMinutes(1);
        }

        return  dataOfdate;
    }
}